/*============================================================================*/
/*  Copyright (C) 2009-2011, iSOFT INFRASTRUCTURE SOFTWARE CO.,LTD.
 *  
 *  All rights reserved. This software is iSOFT property. Duplication 
 *  or disclosure without iSOFT written authorization is prohibited.
 *  
 *  @file       <Xcp_Std.c>
 *  @brief      <Xcp Module Daq Section C file.>
 *  
 *  <Compiler: Codewarrior for mpc55xx v2.6     MCU:MPC56XX>
 *  
 *  @author     <Dongyuan.Sun, Qitao.Yu>
 *  @date       <2013-03-06>
 */
/*============================================================================*/

/*=======[R E V I S I O N   H I S T O R Y]====================================*/
/*  <VERSION>    <DATE>    <AUTHOR>                    <REVISION LOG>
 *  V1.0.0       20130306  Dongyuan.Sun, Qitao.Yu      Initial version
 * 
 */
/*============================================================================*/

/*=======[V E R S I O N  I N F O R M A T I O N]===============================*/
#define XCP_STD_C_AR_MAJOR_VERSION  4
#define XCP_STD_C_AR_MINOR_VERSION  0
#define XCP_STD_C_AR_PATCH_VERSION  3
#define XCP_STD_C_SW_MAJOR_VERSION  1
#define XCP_STD_C_SW_MINOR_VERSION  0
#define XCP_STD_C_SW_PATCH_VERSION  0

/*=======[I N C L U D E S]====================================================*/
#include "Xcp.h"
#include "Xcp_Internal.h"

/*=======[V E R S I O N  C H E C K]===========================================*/
#if (XCP_STD_C_AR_MAJOR_VERSION != XCP_H_AR_MAJOR_VERSION)
  #error "Xcp_Std.c : Mismatch in Specification Major Version"
#endif
#if (XCP_STD_C_AR_MINOR_VERSION != XCP_H_AR_MINOR_VERSION)
  #error "Xcp_Std.c : Mismatch in Specification Major Version"
#endif
#if (XCP_STD_C_AR_PATCH_VERSION != XCP_H_AR_PATCH_VERSION)
  #error "Xcp_Std.c : Mismatch in Specification Major Version"
#endif
#if (XCP_STD_C_SW_MAJOR_VERSION != XCP_H_SW_MAJOR_VERSION)
  #error "Xcp_Std.c : Mismatch in Specification Major Version"
#endif
#if (XCP_STD_C_SW_MINOR_VERSION != XCP_H_SW_MINOR_VERSION)
  #error "Xcp_Std.c : Mismatch in Specification Major Version"
#endif
#if (XCP_STD_C_SW_PATCH_VERSION != XCP_H_SW_PATCH_VERSION)
  #error "Xcp_Std.c : Mismatch in Specification Major Version"
#endif

/*=======[M A C R O S]========================================================*/
#define XCP_CONNECT_MODE_OFFSET         0x01u
#define XCP_CONNECT_MODE_NORMAL         0x00u
#define XCP_CONNECT_MODE_USER           0x01u

#if (XCP_SEED_AND_UNLOCK == STD_ON)
#define XCP_SEED_MAX_LENGTH             0x10u
#define XCP_KEY_MAX_LENGTH              0x20u
#define XCP_GET_SEED_DATA_OFFSET        0x02u
#define XCP_UNLOCK_DATA_OFFSET          0x02u
#endif
 
/*=======[T Y P E   D E F I N I T I O N S]====================================*/
#if (XCP_ON_CAN_ENABLE == STD_ON)
    #if (XCP_GET_SLAVE_ID == STD_ON)
    /* Xcp On CAN Get Slave Id  status */
    typedef enum
    {
    	XCP_GETSLAVEID_IDLE,
    	XCP_GETSLAVEID_POSTIVE_STATUS
    }Xcp_GetSlaveIdStatusType;
    #endif
#endif

/*=======[E X T E R N A L   D A T A]==========================================*/

#if (XCP_SET_MTA == STD_ON)
VAR(Xcp_AddressType, XCP_VAR) Xcp_MTA =
{
    0,
    0
};
#endif

/*=======[I N T E R N A L   D A T A]==========================================*/
#if (XCP_SEED_AND_UNLOCK == STD_ON)
VAR(Xcp_SeedandKeyStatusType, XCP_VAR) Xcp_SeedandKeyStatus = XCP_PRE_SEED;
VAR(uint8, XCP_VAR) Xcp_SeedandKeyRes = 0u;
STATIC VAR(uint8, XCP_VAR) Xcp_SeedandKeyLen = 0u;
STATIC VAR(uint8, XCP_VAR) Xcp_SeedandKeyPos = 0u;
STATIC VAR(uint8, XCP_VAR) Xcp_SeedBuffer[XCP_SEED_MAX_LENGTH];
STATIC VAR(uint8, XCP_VAR) Xcp_KeyBuffer[XCP_KEY_MAX_LENGTH];
STATIC VAR(uint8, XCP_VAR) Xcp_SeedLen = 0u;
STATIC VAR(uint8, XCP_VAR) Xcp_KeyLen = 0u;
#endif

/*=======[I N T E R N A L   F U N C T I O N   D E C L A R A T I O N S]========*/
/*
 * Complex Command Handler
 */

#if (XCP_SEED_AND_UNLOCK == STD_ON)
STATIC FUNC(void, XCP_CODE) Xcp_CopySeedIntoFrame(void);
STATIC FUNC(void, XCP_CODE) Xcp_GetSeedHal(void);
STATIC FUNC(void, XCP_CODE) Xcp_KeyHandler(uint8 len);
#endif

#if (XCP_UPLOAD == STD_ON)
STATIC FUNC(void, XCP_CODE) Xcp_UploadHal(void);
#endif
#if (XCP_SHORT_UPLOAD == STD_ON)
STATIC FUNC(void, XCP_CODE) Xcp_ShortUploadHal(void);
#endif
/*=======[F U N C T I O N   I M P L E M E N T A T I O N S]====================*/
/*
 * S T D   m a n d a t o r y    c o m m a n d
 */
/******************************************************************************/
/**
 * @brief               <Command Connect Handler>
 * 
 * <This Function handle the connect command.>
 *
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>    
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_Connect(void)
{
    const Xcp_GernalType* gernalCfgRef = Xcp_LocalCfgPtr->XcpGernalRef;
    uint8 commModeBasic = XCP_ADDRESS_GRANULARITY<<0x01;
    
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 2u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    if (XCP_UINIT == Xcp_Status)
    {
        Xcp_SetErrorCode(XCP_ERR_RES_TEMP_NOT_A);
        Xcp_RespLength = 0x02u;
    }
    else
    {
        #if (XCP_GET_COMM_MODE_INFO == STD_ON)
        commModeBasic |= 0x80u;
        #endif
        #if (XCP_SLAVE_BLOCK_MODE == STD_ON)
        commModeBasic |= 0x40u;
        #endif
        #if (CPU_BYTE_ORDER == HIGH_BYTE_FIRST)
        commModeBasic |= 0x01u;
        #endif
        
        if (XCP_CONNECT_MODE_NORMAL == Xcp_CmdBuffer[XCP_CONNECT_MODE_OFFSET])
        {
            Xcp_Status = XCP_PRE_CONNECT;
            Xcp_RespBuffer[1] = XCP_RESOURCE;
            Xcp_RespBuffer[2] = commModeBasic;
            Xcp_RespBuffer[3] = gernalCfgRef->Xcp_MaxCto;
            Xcp_RespBuffer[6] = XCP_PROTOCOL_VERSIOM_MAJOR;
            Xcp_RespBuffer[7] = XCP_CAN_TRANSPORT_LAYER_VERION_MAJOR;
            Xcp_CopyU2ToU1Buffer(gernalCfgRef->Xcp_MaxDto, &Xcp_RespBuffer[4], CPU_BYTE_ORDER);
            Xcp_RespLength = 0x08u;
        }
        else if (XCP_CONNECT_MODE_USER == Xcp_CmdBuffer[XCP_CONNECT_MODE_OFFSET])
        {
            Xcp_Status = XCP_PRE_USERDEFINE;
            Xcp_RespBuffer[1] = XCP_RESOURCE;
            Xcp_RespBuffer[2] = commModeBasic;
            Xcp_RespBuffer[3] = gernalCfgRef->Xcp_MaxCto;
            Xcp_RespBuffer[6] = XCP_PROTOCOL_VERSIOM_MAJOR;
            Xcp_RespBuffer[7] = XCP_CAN_TRANSPORT_LAYER_VERION_MAJOR;
            Xcp_CopyU2ToU1Buffer(gernalCfgRef->Xcp_MaxDto, &Xcp_RespBuffer[4], CPU_BYTE_ORDER);
            Xcp_RespLength = 0x08u;
        }
        else
        {
            Xcp_SetErrorCode(XCP_ERR_OUT_OF_RANGE);
            Xcp_RespLength = 0x02u;
        }
    }
    Xcp_SendResp();
    return;
}

/******************************************************************************/
/**
 * @brief               <Disconnect Handler>
 * 
 * <This Function init. DAQ state and general variables and put stack state into
 *  Disconnect.>
 *
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>    
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_DisconnectHal(void)
{
	#if (XCP_PAG_SUPPORT == STD_ON)
	#if (XCP_MMU_SUPPORT == STD_OFF)
    uint8 segNum = 0;
	#endif
	#endif	
    /* Disable Command Proccessor */
    Xcp_Status = XCP_SLEEP;
    #if (XCP_PL_DAQ == (XCP_PL_DAQ & XCP_RESOURCE))
    /* Disable Daq Proccessor */
    Xcp_DAQReinit();
    #endif
    Xcp_ClearStatus();

	#if (XCP_PAG_SUPPORT == STD_ON)
	#if (XCP_MMU_SUPPORT == STD_OFF)
    /* XCP send SET_CAL_PAGE,did not send the correct page, so when disconnect,
     * it should clear the state of cal page number to RAM */
    for (segNum = 0; segNum < Xcp_SegmentInfo.maxSegNum; segNum++)
	{
		Xcp_ActivPagNum[segNum] = XCP_RAM_PAGE_NUM;
	}
	#endif
	#endif
    Xcp_Status = XCP_DISCONNECT;
}

/******************************************************************************/
/**
 * @brief               <Command Disconnect Handler>
 * 
 * <This Function handle the disconnect command.>
 *
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>    
 */
/******************************************************************************/
FUNC(void,XCP_CODE) Xcp_Disconnect(void)
{
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 1u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    {
        Xcp_DisconnectHal();
        Xcp_RespLength = 0x01u;
    }
    Xcp_SendResp();
    return;
}

/******************************************************************************/
/*
 * @brief               <Command GetStatus Handler>
 * 
 * < Get The current status > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>    
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_GetStatus(void)
{
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED)\
        && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 1u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif    
    {        
        Xcp_RespBuffer[1u] = Xcp_SessionStatus;
        Xcp_RespBuffer[2u] = Xcp_ProtectionStatus;
        Xcp_CopyU2ToU1Buffer(Xcp_SessionCfgId, &Xcp_RespBuffer[4u], CPU_BYTE_ORDER);
        Xcp_RespLength = 0x06u;
    }
    Xcp_SendResp();
    return;
}

/******************************************************************************/
/*
 * @brief               <Command Synch Handler>
 * 
 * < Get The current status > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>    
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_Synch(void)
{
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 1u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    {
    	#if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
        /* PGM handler */
        if (Xcp_PgmStauts != XCP_PGM_IDLE)
        {
            /* Do Nothing */
        }
        else
        #endif
        {
            Xcp_CommandInit();
        }        
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNCH);
        Xcp_RespLength = 0x02u;
    }
    Xcp_SendResp();
    return;
}

/*
 * S T D   o p t i o n a l    c o m m a n d
 */
#if (XCP_GET_COMM_MODE_INFO == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command GetCommModeInfo Handler>
 * 
 * < This command returns optional information on different Communication Modes 
 *   supported by the slave> .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>    
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_GetCommModeInfo(void)
{
    const Xcp_GernalType* gernalCfgRef = Xcp_LocalCfgPtr->XcpGernalRef;
    
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 1u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif    
    {  
        #if (XCP_MASTER_BLOCK_MODE == STD_ON)
        Xcp_RespBuffer[2u] = 0x01u;
        Xcp_RespBuffer[4u] = gernalCfgRef->Xcp_MaxBs;        
        Xcp_RespBuffer[5u] = gernalCfgRef->Xcp_MinSt;
        #elif (XCP_INTERLEAVED_MODE == STD_ON)
        Xcp_RespBuffer[2u] = 0x02u;
        Xcp_RespBuffer[6u] = gernalCfgRef->Xcp_QueueSize;
        #else
        Xcp_RespBuffer[2u] = 0x00u;
        Xcp_RespBuffer[4u] = 0x00u;
        Xcp_RespBuffer[5u] = 0x00u;
        Xcp_RespBuffer[6u] = 0x00u;
        #endif
        /* XCP Driver Version Number */
        Xcp_RespBuffer[7u] = ((XCP_STD_C_SW_MAJOR_VERSION&0x0fu) << 4u)
                                    |(XCP_STD_C_SW_MINOR_VERSION&0x0fu);
        Xcp_RespLength = 0x08u;
    }
    Xcp_SendResp();
    return;
}
#endif /*XCP_GET_COMM_MODE_INFO == STD_ON*/

#if (XCP_GET_ID == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command GetId Handler>
 * 
 * < This command is used for automatic session configuration and for slave 
 *   device identification> .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>    
 */
/******************************************************************************/
FUNC(void,XCP_CODE) Xcp_GetId(void)
{
    uint8 getIdReqIdType;
    uint8 idNum;
    const Xcp_IdInfoType * localInfoCfgRef = Xcp_LocalCfgPtr->XcpGernalRef->Xcp_IdInfoPtr;
    const uint8 numOfId = Xcp_LocalCfgPtr->XcpGernalRef->Xcp_IdInfoNum;
    
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 2u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif    
    {  
        /* get the mode from CommandRxObject[1] buffer */
        getIdReqIdType = Xcp_CmdBuffer[1u];

        for (idNum = 0u; idNum < numOfId; idNum++)
        {
            if (getIdReqIdType == localInfoCfgRef[idNum].type)
            {
                /* Set the MTA so that the master can upload the ID string. */
                Xcp_MTA.transferAddr = (uint32)(localInfoCfgRef[idNum].ptr);
                Xcp_MTA.extension = 0x0u;
                Xcp_RespBuffer[1u] = localInfoCfgRef[idNum].mode;
                /* Xcp_RespBuffer[2-3] are Reserved */
                /* Put the length to RespBuffer[4]-[7] buffer */
                Xcp_UploadInfoLen = ((localInfoCfgRef[idNum].length - 1) / XCP_AG) + 1;
                Xcp_CopyU4ToU1Buffer(localInfoCfgRef[idNum].length, 
                            &(Xcp_RespBuffer[4u]), CPU_BYTE_ORDER);  
                /* Number of Data Elements UPLOAD [AG] = (Length GET_ID [BYTE]) / AG */
                Xcp_RespLength = 0x08u;
                break;
            }/* end of if (Xcp_GetId_Req_IdType == Xcp_IdInfo[i].type)*/
        }
        /* for id is not available */
        if (idNum ==  numOfId)
        {
            Xcp_RespBuffer[1u] = 0x0u;
            /* length = 0 */
            Xcp_RespBuffer[4u] = 0x0u;
            Xcp_RespBuffer[5u] = 0x0u;
            Xcp_RespBuffer[6u] = 0x0u;
            Xcp_RespBuffer[7u] = 0x0u;
            Xcp_RespLength = 0x08u;
        }
    }
    Xcp_SendResp();
    return;
}
#endif /* XCP_GET_ID == STD_ON*/

#if (XCP_SET_REQUEST == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command SetRequest Handler>
 * 
 * < This command is used to start a asychronous task for storing CAL or DAQ list>.
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None>    
 */
/******************************************************************************/
FUNC(void,XCP_CODE) Xcp_SetRequest(void)
{
    /* do not realize this service */
    Xcp_SetErrorCode(XCP_ERR_CMD_UNKNOWN);
    Xcp_RespLength = 0x02u;
    Xcp_SendResp();
    return;
}
#endif

#if (XCP_SEED_AND_UNLOCK == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command SetRequest Handler>
 * 
 * < This command is used to start a asychronous task for storing CAL or DAQ list>.
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
STATIC FUNC(void, XCP_CODE) Xcp_CopySeedIntoFrame(void)
{
    uint8 pos;
    uint8 maxcto = Xcp_LocalCfgPtr->XcpGernalRef->Xcp_MaxCto;
    /* copy seed into frame buffer */
    Xcp_RespBuffer[1] = Xcp_SeedandKeyLen;
    if (Xcp_SeedandKeyLen > (maxcto - XCP_UNLOCK_DATA_OFFSET))
    {
        for (pos = XCP_GET_SEED_DATA_OFFSET; pos < maxcto; pos++)
        {
            Xcp_RespBuffer[pos] = Xcp_SeedBuffer[Xcp_SeedandKeyPos];
            Xcp_SeedandKeyPos++;
        }
        Xcp_SeedandKeyLen -= (maxcto - XCP_UNLOCK_DATA_OFFSET);
        Xcp_SeedandKeyStatus = XCP_SEED;
        Xcp_RespLength = maxcto;
    }
    else
    {
        for (pos = 0; pos < Xcp_SeedandKeyLen; pos++)
        {
            Xcp_RespBuffer[XCP_GET_SEED_DATA_OFFSET + pos] 
                       = Xcp_SeedBuffer[Xcp_SeedandKeyPos];
            Xcp_SeedandKeyPos++;
        }                        
        Xcp_SeedandKeyStatus = XCP_PRE_KEY;
        Xcp_RespLength = (PduLengthType)(Xcp_SeedandKeyLen + XCP_UNLOCK_DATA_OFFSET);
    }
    return;
}

STATIC FUNC(void, XCP_CODE) Xcp_GetSeedHal(void)
{
    uint8 tMode = Xcp_CmdBuffer[0x01];
    uint8 resource = Xcp_CmdBuffer[0x02];

    switch (tMode)
    {
        /* (first part of) seed */
        case 0x00:
        {
            /* check Resource*/
            if ((0 != resource)
            && (XCP_RESOURCE == (XCP_RESOURCE|resource))
            && ((XCP_PL_CAL == (XCP_PL_CAL|resource))
            || (XCP_PL_DAQ == (XCP_PL_DAQ|resource))
            || (XCP_PL_PGM == (XCP_PL_PGM|resource))
            || (XCP_PL_STIM == (XCP_PL_STIM|resource)))
            )
            {
                Xcp_SeedandKeyRes = resource;
                /* in case resource unprotected reurn len = 0 */
                if (0x00 == (resource & Xcp_ProtectionStatus))
                {
                    Xcp_RespBuffer[1] = 0;
                    Xcp_RespLength = 0x02u;
                    Xcp_SeedandKeyStatus = XCP_PRE_SEED;
                }
                /* call seed calculate function */
                else if (E_OK ==  Xcp_CreateSeed(&Xcp_SeedLen, Xcp_SeedBuffer, resource))
                {
                    /* init Seed Buffer status*/
                    Xcp_SeedandKeyPos = 0;
                    Xcp_SeedandKeyLen = Xcp_SeedLen;
                    /* update frame buffer */
                    Xcp_CopySeedIntoFrame();
                }
                else
                {
                    Xcp_SetErrorCode(XCP_ERR_RES_TEMP_NOT_A);
                    Xcp_RespLength = 0x02u;
                }
            }
            /* resource error */
            else
            {
                Xcp_SetErrorCode(XCP_ERR_OUT_OF_RANGE);
                Xcp_RespLength = 0x02u;
            }
            break;
        }
        /* continued frame */
        case 0x01:
        {
            if ((XCP_SEED == Xcp_SeedandKeyStatus)
            && (Xcp_SeedandKeyRes == resource))
            {
                /* update frame buffer */
                Xcp_CopySeedIntoFrame();
            }
            /* resource consistency error
             * or sequence error
             */
            else
            {
                Xcp_SeedandKeyStatus = XCP_PRE_SEED;
                Xcp_SetErrorCode(XCP_ERR_SEQUENCE);
                Xcp_RespLength = 0x02u;                    
            }
            break;
        }
        /* mode error */
        default:
        {
            Xcp_SetErrorCode(XCP_ERR_MODE_NOT_VALID);
            Xcp_RespLength = 0x02u;
            break;
        }
    }
    return;
}
/******************************************************************************/
/*
 * @brief               <Command GetSeed Handler>
 * 
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_GetSeed(void)
{

    /* length check */
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 3u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif 
    {
        Xcp_GetSeedHal();
    }
    Xcp_SendResp();
    return;
}

/******************************************************************************/
/*
 * @brief               <Command GetSeed Handler>
 * 
 * < This function copy key data from frame into buffer and check its validity > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
STATIC FUNC(void, XCP_CODE) Xcp_KeyHandler(uint8 len)
{
    uint8 pos;
    uint8 maxcto = Xcp_LocalCfgPtr->XcpGernalRef->Xcp_MaxCto;
    boolean result;

    /* key in multi frames */
    if (len > (maxcto - XCP_UNLOCK_DATA_OFFSET))
    {
        for (pos = 0; pos < (maxcto - XCP_UNLOCK_DATA_OFFSET); pos++)
        {
            Xcp_KeyBuffer[Xcp_SeedandKeyPos + pos] = Xcp_CmdBuffer[pos + XCP_UNLOCK_DATA_OFFSET];            
        }
        Xcp_SeedandKeyPos += pos;
        Xcp_SeedandKeyLen -= (maxcto - XCP_UNLOCK_DATA_OFFSET);
        Xcp_RespBuffer[1] = Xcp_ProtectionStatus;
        Xcp_RespLength = 0x02;
    }
    /* key in this frame */
    else
    {
        /* copy last data frame */
        for (pos = 0; pos < len; pos++)
        {
            Xcp_KeyBuffer[Xcp_SeedandKeyPos + pos] = Xcp_CmdBuffer[pos + XCP_UNLOCK_DATA_OFFSET];
        }
        /* check validity */
        result = Xcp_IsKeyRight(Xcp_SeedBuffer, Xcp_KeyBuffer, 
                  Xcp_SeedLen, Xcp_KeyLen, Xcp_SeedandKeyRes);
        /* valid key */
        if (TRUE == result)
        {
            Xcp_ProtectionStatus &= (uint8)(~Xcp_SeedandKeyRes);
            Xcp_RespBuffer[1] = Xcp_ProtectionStatus;
            Xcp_RespLength = 0x02;
        }
        /* unvalid key */
        else
        {
            Xcp_DisconnectHal();
            Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
            Xcp_RespLength = 0x02u;
        }
        Xcp_SeedandKeyStatus = XCP_PRE_SEED;
    }
    return;
}

/******************************************************************************/
/*
 * @brief               <Command Unlock>
 * 
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_Unlock(void)
{

    uint8 len = Xcp_CmdBuffer[0x01];
    /* length check */
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != (len + 2))
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif 
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    {
        /* normal function */
        if (XCP_PRE_KEY == Xcp_SeedandKeyStatus)
        {
            if (len > XCP_KEY_MAX_LENGTH)
            {
                Xcp_SeedandKeyStatus = XCP_PRE_SEED;
                Xcp_DisconnectHal();
                Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
                Xcp_RespLength = 0x02u;
            }
            else
            {
                Xcp_KeyLen = len;
                Xcp_SeedandKeyLen = len;
                Xcp_SeedandKeyPos = 0;
                Xcp_SeedandKeyStatus = XCP_KEY;
                /* call key handler */
                Xcp_KeyHandler(len);
            }
        }
        else if (XCP_KEY == Xcp_SeedandKeyStatus)
        {
            if (len == Xcp_SeedandKeyLen)
            {
                /* call key handler */
                Xcp_KeyHandler(len);
            }
            else
            {
                Xcp_SeedandKeyStatus = XCP_PRE_SEED;
                Xcp_SetErrorCode(XCP_ERR_SEQUENCE);
                Xcp_RespLength = 0x02u;
            }
        }
        /* err sequnce */
        else
        {
            Xcp_SeedandKeyStatus = XCP_PRE_SEED;
            Xcp_SetErrorCode(XCP_ERR_SEQUENCE);
            Xcp_RespLength = 0x02u;
        }
    }
    Xcp_SendResp();
    return;
}
#endif /* XCP_SEED_AND_UNLOCK == STD_ON */

#if (XCP_SET_MTA == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command SetMta>
 * 
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_SetMta(void)
{
    uint8 extAddr = Xcp_CmdBuffer[3];
    uint32 Addr;

    Xcp_CopyU1BufferToU4(&Xcp_CmdBuffer[4], &Addr, CPU_BYTE_ORDER);
    
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 8u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif 
    if (TRUE == Xcp_CheckAddress(Xcp_Mta2Ptr(extAddr, Addr), 0, XCP_MEM_ALL))
    {
        Xcp_MTA.extension = extAddr;
        Xcp_MTA.transferAddr = Addr;
        Xcp_UploadInfoLen = 0x00u;
    }
    else
    {
        Xcp_SetErrorCode(XCP_ERR_OUT_OF_RANGE);
        Xcp_RespLength = 0x02u;
    }
    Xcp_SendResp();
    return;
}
#endif

#if (XCP_UPLOAD == STD_ON)
STATIC FUNC(void, XCP_CODE) Xcp_UploadHal(void)
{
    uint8 len = Xcp_CmdBuffer[1];
    Xcp_AGType* sourPtr;
    Xcp_AGType* destPtr;
    uint8 pos;
    
    if ((0x00u == len)
    #if (XCP_SLAVE_BLOCK_MODE == STD_OFF)
    || (len > XCP_UPLOAD_SIZE)
    #endif
    )
    {
        Xcp_SetErrorCode(XCP_ERR_OUT_OF_RANGE);
        Xcp_RespLength = 0x02u;
    }   
    else if ((TRUE == Xcp_CheckAddress(Xcp_Mta2Ptr(Xcp_MTA.extension, Xcp_MTA.transferAddr), 
                                                            (len*XCP_AG), XCP_MEM_ALL))
    || (len <= Xcp_UploadInfoLen))
    {
        #if (XCP_SLAVE_BLOCK_MODE == STD_ON)
        if (len <= XCP_UPLOAD_SIZE)
        #endif
        {
            /* get pointer from MTA */
            sourPtr = (Xcp_AGType*)Xcp_Mta2Ptr(Xcp_MTA.extension, Xcp_MTA.transferAddr);
            destPtr = (Xcp_AGType*)(&Xcp_RespBuffer[XCP_UPLOAD_DATA_OFFSET]);
            for (pos = 0; pos < len; pos++)
            {
                destPtr[pos] = sourPtr[pos];
            }
            /* copy data into buffer */
            Xcp_UpdateMTA(len*XCP_AG);
            Xcp_RespLength = (uint16)((len * XCP_AG) + XCP_UPLOAD_DATA_OFFSET);
        }
        #if (XCP_SLAVE_BLOCK_MODE == STD_ON)
        else
        {
            Xcp_BlockBufferPos = 0;
            Xcp_BlockBufferLen = len;
            Xcp_CommandStatus = XCP_CMD_BLOCK_TRANSF;
        }
        #endif
    }
    else
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_DENIED);
        Xcp_RespLength = 0x02u;
    }

    return;
}

/******************************************************************************/
/*
 * @brief               <Command SetMta>
 * 
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_Upload(void)
{    
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 2u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif 
    if ((XCP_PL_CAL == (Xcp_ProtectionStatus & XCP_PL_CAL))
    && (XCP_PL_PGM == (Xcp_ProtectionStatus & XCP_PL_PGM))
    && (XCP_PL_DAQ == (Xcp_ProtectionStatus & XCP_PL_DAQ)))
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
        Xcp_RespLength = 0x02u;
    }
    else
    {
        Xcp_UploadHal();
    }
    Xcp_SendResp();
    return;
}
#endif

#if (XCP_SHORT_UPLOAD == STD_ON)
STATIC FUNC(void, XCP_CODE) Xcp_ShortUploadHal(void)
{
    uint8 len = Xcp_CmdBuffer[1];
    uint8 extAddr = Xcp_CmdBuffer[3];
    uint32 Addr;
    Xcp_AGType* sourPtr;
    Xcp_AGType* destPtr;
    uint8 pos;
    Xcp_CopyU1BufferToU4(&Xcp_CmdBuffer[4], &Addr, CPU_BYTE_ORDER);

    if ((0x00u == len)
    || (len > XCP_UPLOAD_SIZE))
    {
        Xcp_SetErrorCode(XCP_ERR_OUT_OF_RANGE);
        Xcp_RespLength = 0x02u;
    }
    else if (TRUE == Xcp_CheckAddress(Xcp_Mta2Ptr(extAddr, Addr), 
                                       (len*XCP_AG), XCP_MEM_ALL))
    {
        /* Set MTA */
        Xcp_MTA.extension = extAddr;
        Xcp_MTA.transferAddr = Addr;
        /* get pointer from MTA */
        sourPtr = (Xcp_AGType*)Xcp_Mta2Ptr(Xcp_MTA.extension, Xcp_MTA.transferAddr);
        destPtr = (Xcp_AGType*)(&Xcp_RespBuffer[XCP_UPLOAD_DATA_OFFSET]);
        /* copy data into buffer */
        for (pos = 0; pos < len; pos++)
        {
            destPtr[pos] = sourPtr[pos];
        }
        Xcp_UpdateMTA(len*XCP_AG);
        Xcp_RespLength = (uint16)((len * XCP_AG) + XCP_UPLOAD_DATA_OFFSET);
    }
    else
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_DENIED);
        Xcp_RespLength = 0x02u;
    }
    return;
}

/******************************************************************************/
/*
 * @brief               <Command ShortUpload>
 * 
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_ShortUpload(void)
{
    Xcp_UploadInfoLen = 0;
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if (Xcp_CmdLength != XCP_CAN_MAX_DLC)
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif 
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    if (XCP_PL_CAL == (Xcp_ProtectionStatus & XCP_PL_CAL))
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
        Xcp_RespLength = 0x02u;
    }
    else
    {
        Xcp_ShortUploadHal();
    }
    Xcp_SendResp();
    return;
}
#endif

#if (XCP_BUILD_CHECKSUM == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command BuildChecksum>
 * 
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_BuildChecksum(void)
{
    uint32 crcResult;
    uint32 blockSize;
    uint32 checksumStartAddress;
    uint32 maxChecksumBlockSize = Xcp_LocalCfgPtr->XcpGernalRef->Xcp_ChksumMaxSize;
    
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if (Xcp_CmdLength != XCP_CAN_MAX_DLC)
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    if ((XCP_PL_CAL == (Xcp_ProtectionStatus & XCP_PL_CAL))
    && ((XCP_PL_PGM == (Xcp_ProtectionStatus & XCP_PL_PGM))))
    {
        Xcp_SetErrorCode(XCP_ERR_ACCESS_LOCKED);
        Xcp_RespLength = 0x02u;
    }
    else
    {  
        /* get block size from CTO buffer[4-7] */
        Xcp_CopyU1BufferToU4(&Xcp_CmdBuffer[4u], &blockSize, CPU_BYTE_ORDER);
        /* get bolck start address */
        checksumStartAddress  = Xcp_Mta2Ptr(Xcp_MTA.extension,Xcp_MTA.transferAddr);

        if (blockSize > maxChecksumBlockSize)
        {
            Xcp_SetErrorCode(XCP_ERR_OUT_OF_RANGE);
            
            /* Put the MAX_CHECKSUM_BLOCKSIZE to RespBuffer[4]-[7] buffer */
            Xcp_CopyU4ToU1Buffer(maxChecksumBlockSize, &(Xcp_RespBuffer[4u]), CPU_BYTE_ORDER);  
            Xcp_RespLength = 0x08u;
        }
        /* address check */
        else if (FALSE == Xcp_CheckAddress(checksumStartAddress, 
                                        blockSize, XCP_MEM_CAL_ALL))
        {
            Xcp_SetErrorCode(XCP_ERR_ACCESS_DENIED);
            Xcp_RespLength = 0x02u;
        }
        else
        {
            /* set checksum type */
            Xcp_RespBuffer[1u] = XCP_CHECKSUM_TYPE_CRC_16_CITT;
            /* call user interface  Ccp_ChecksumCompute to set the crcResult and retrun the size of cheksum*/
            Xcp_ChecksumCompute(checksumStartAddress, (blockSize*XCP_AG), &crcResult);
            Xcp_CopyU4ToU1Buffer(crcResult, &(Xcp_RespBuffer[4u]), CPU_BYTE_ORDER);  
            Xcp_UpdateMTA(blockSize*XCP_AG);
            Xcp_RespLength = 0x08u;            
        }
    }
    Xcp_SendResp();
    return;
}
#endif

/* Transport Layer Command */
#if (XCP_GET_SLAVE_ID == STD_ON)
/******************************************************************************/
/*
 * @brief               <Command GetSlaveId>
 * 
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
FUNC(void, XCP_CODE) Xcp_GetSlaveId(void)
{
    uint8 getSlaveMode; 
    uint32 canIdForStimCmd;
    STATIC Xcp_GetSlaveIdStatusType Xcp_GetSlaveIdStatus = XCP_GETSLAVEID_IDLE;
    
    #if ((STD_OFF == XCP_CAN_MAX_DLC_REQUIRED) && (STD_ON == XCP_ON_CAN_ENABLE))
    if ((Xcp_CmdLength != 0x06u)
    && (Xcp_CmdLength != XCP_CAN_MAX_DLC))
    {
        Xcp_SetErrorCode(XCP_ERR_CMD_SYNTAX);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    #if (XCP_PL_PGM == (XCP_PL_PGM & XCP_RESOURCE))
    if (Xcp_PgmStauts != XCP_PGM_IDLE)
    {
        Xcp_SetErrorCode(XCP_ERR_PGM_ACTIVE);
        Xcp_RespLength = 0x02u;
    }
    else
    #endif
    {  
        getSlaveMode = Xcp_CmdBuffer[5u];
        
        if ((0x58u == Xcp_CmdBuffer[2u])    /**< 'X'*/
           &&(0x43u == Xcp_CmdBuffer[3u])   /**< 'C'*/
           &&(0x50u == Xcp_CmdBuffer[4u]))  /**< 'P'*/
        {
            switch (getSlaveMode)
            {
                /* identify by echo */
                case 0u:
                {
                    Xcp_RespBuffer[1u] = 0x58u; /**< 'X'*/
                    Xcp_RespBuffer[2u] = 0x43u; /**< 'C'*/
                    Xcp_RespBuffer[3u] = 0x50u; /**< 'P'*/

                    /* Get the Canid Used for STIM and CMD from Configuration */
                    canIdForStimCmd = Xcp_LocalCfgPtr->XcpCtoRxPduRef->XcpRxPduCanId;
                  
                    /* Put the canid to RespBuffer[4]-[7] buffer in INTEL format */
                    Xcp_CopyU4ToU1Buffer(canIdForStimCmd, &(Xcp_RespBuffer[4u]), LOW_BYTE_FIRST); 

                    /* response length is 8 */
                    Xcp_RespLength = 0x08u;

                    /* Set The status to XCP_GETSLAVEID_POSTIVE_STATUS */
                    Xcp_GetSlaveIdStatus = XCP_GETSLAVEID_POSTIVE_STATUS;
                    break;
                }
                /* confirm by inverse echo */
                case 1u:
                {
                    if (XCP_GETSLAVEID_POSTIVE_STATUS == Xcp_GetSlaveIdStatus)
                    {
                        Xcp_RespBuffer[1u] = 0xA7u; /**< '~X'*/
                        Xcp_RespBuffer[2u] = 0xBCu; /**< '~C'*/
                        Xcp_RespBuffer[3u] = 0xAFu; /**< '~P'*/

                        /* Get the Canid Used for STIM and CMD from Configuration */
                        canIdForStimCmd = Xcp_LocalCfgPtr->XcpCtoRxPduRef->XcpRxPduCanId;
                      
                        /* Put the canid to RespBuffer[4]-[7] buffer in INTEL format */
                        Xcp_CopyU4ToU1Buffer(canIdForStimCmd, &Xcp_RespBuffer[4u], LOW_BYTE_FIRST); 

                        /* response length is 8 */
                        Xcp_RespLength = 0x08u;

                        /* Set The status back to XCP_GETSLAVEID_IDLE */
                        Xcp_GetSlaveIdStatus = XCP_GETSLAVEID_IDLE;
                    }
                    else
                    {
                        /* without a previous GET_SLAVE_ID(identify by echo), 
                         * the slaves will silently ignore the command.
                         */
                        Xcp_CommandStatus = XCP_CMD_IDLE;
                    }
                    break;
                }
                /* mode error */
                default:
                {
                    Xcp_SetErrorCode(XCP_ERR_OUT_OF_RANGE);
                    Xcp_RespLength = 0x02u;    
                    break;
                }
            }
        }
        else
        {
            /* command value not correct */
            Xcp_CommandStatus = XCP_CMD_IDLE;
        }        
    }
    if (XCP_CMD_IDLE != Xcp_CommandStatus)
    {
        Xcp_SendResp();
    }
    return;
}
#endif /* XCP_GET_SLAVE_ID == STD_ON */

#if (XCP_SET_MTA == STD_ON)
/******************************************************************************/
/*
 * @brief               <update MTA>
 * 
 * < > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <None>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
FUNC(void,XCP_CODE) Xcp_UpdateMTA(uint32 u4Length)
{
    /* updata the MTA */
    Xcp_MTA.transferAddr += u4Length;
    if (0x00u != Xcp_UploadInfoLen)
    {
        if (Xcp_UploadInfoLen >= (u4Length / XCP_AG))
        {
            Xcp_UploadInfoLen -= (u4Length / XCP_AG);
        }
        else
        {
            Xcp_UploadInfoLen = 0;
        }
    }
    return;
}

/******************************************************************************/
/*
 * @brief               <Dest. Addr. check function>
 * 
 * < This function is used to validate the input addr. and size > .
 * Service ID   :       <None>
 * Sync/Async   :       <Synchronous>
 * Reentrancy           <Not Reentrant>
 * @param[in]           <addr, size, type>
 * @param[out]          <None>
 * @param[in/out]       <None>
 * @return              <None> 
 */
/******************************************************************************/
FUNC(boolean, XCP_CODE) Xcp_CheckAddress(uint32 addr, uint32 size, Xcp_AddressTypeType type)
{
    boolean result = FALSE;
    uint8 segmentNum;
    
    switch(type)
    { 
        case XCP_MEM_ALL:
        {
            if (((addr >= (Xcp_SegmentInfo.measurementRomStart))
            		&& (((addr + size) - 1) <= (Xcp_SegmentInfo.measurementRomEnd)))
            ||((addr >= (Xcp_SegmentInfo.measurementRamStart))
            	    && (((addr + size) - 1) <= (Xcp_SegmentInfo.measurementRamEnd))))
            {
            	result = TRUE;
                break;
            }
            else
            {
                #if (XCP_PL_CAL == (XCP_PL_CAL&XCP_RESOURCE))
                for (segmentNum = 0; segmentNum < (Xcp_SegmentInfo.maxSegNum); segmentNum++)
                {
                    if (
                    #if ((XCP_PAG_SUPPORT == STD_ON)\
                    && (XCP_MMU_SUPPORT == STD_ON))
                        ((addr >= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].dummyRamStart))
                        && (((addr + size) - 1) <= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].dummyRamEnd)))
                    #else
                        ((addr >= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].ramStart))
                        && (((addr + size) - 1) <= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].ramEnd)))
                    #endif                    
                    || ((addr >= Xcp_SegmentInfo.pageInfoPtr[segmentNum].romStart)
                        && (((addr + size) - 1) <= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].romEnd)))
                    )
                    {
                        result = TRUE;
                        break;
                    }
                }
                #endif
                #if (XCP_PL_PGM == (XCP_PL_PGM&XCP_RESOURCE))
                for (segmentNum = 0; segmentNum < XCP_MAX_SECTOR; segmentNum++)
                {
                    if ((addr >= (Xcp_SectorInfo[segmentNum].progStartAddress))
                    && (((addr + size) - 1) <= (Xcp_SectorInfo[segmentNum].progDataSize)))
                    {
                        result = TRUE;
                        break;
                    }
                }
                #endif
            }
            break;
        }
        case XCP_MEM_CAL_ALL:
        #if (XCP_PL_CAL == (XCP_PL_CAL&XCP_RESOURCE))
        {
            for (segmentNum = 0; segmentNum < Xcp_SegmentInfo.maxSegNum; segmentNum++)
            {
                if (
                #if ((XCP_PAG_SUPPORT == STD_ON)\
                && (XCP_MMU_SUPPORT == STD_ON))
                    ((addr >= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].dummyRamStart))
                    && (((addr + size) - 1) <= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].dummyRamEnd)))
                #else
                    ((addr >= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].ramStart))
                    && (((addr + size) - 1) <= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].ramEnd)))
                #endif                    
                || ((addr >= Xcp_SegmentInfo.pageInfoPtr[segmentNum].romStart)
                    && (((addr + size) - 1) <= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].romEnd)))
                )
                {
                    result = TRUE;
                    break;
                }
            }
            break;
        }
        #endif
        case XCP_MEM_CAL_ROM:
        {
            #if (XCP_PL_CAL == (XCP_PL_CAL&XCP_RESOURCE))
            for (segmentNum = 0; segmentNum < Xcp_SegmentInfo.maxSegNum; segmentNum++)
            {
                if ((addr >= Xcp_SegmentInfo.pageInfoPtr[segmentNum].romStart)
                && (((addr + size) - 1) <= Xcp_SegmentInfo.pageInfoPtr[segmentNum].romEnd))
                {
                    result = TRUE;
                    break;
                }
            }
            #endif
            #if (XCP_PL_PGM == (XCP_PL_PGM&XCP_RESOURCE))
            for (segmentNum = 0; segmentNum < XCP_MAX_SECTOR; segmentNum++)
            {
                if ((addr >= Xcp_SectorInfo[segmentNum].progStartAddress)
                && (((addr + size) - 1) <= (Xcp_SectorInfo[segmentNum].progDataSize)))
                {
                    result = TRUE;
                    break;
                }
            }
            #endif
            break;
            
        }
        case XCP_MEM_CAL_RAM:
        {
            #if (XCP_PL_CAL == (XCP_PL_CAL&XCP_RESOURCE))
            for (segmentNum = 0; segmentNum < Xcp_SegmentInfo.maxSegNum; segmentNum++)
            {
                if (((addr >= (Xcp_SegmentInfo.measurementRamStart))
                && (((addr + size) - 1) <= (Xcp_SegmentInfo.measurementRamEnd))))
                {
                    result = TRUE;
                    break;
                }
                else
                #if ((XCP_PAG_SUPPORT == STD_ON)\
                && (XCP_MMU_SUPPORT == STD_ON))
                if ((addr >= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].dummyRamStart))
                    && (((addr + size) - 1) <= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].dummyRamEnd)))
                #else
                if ((addr >= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].ramStart))
                    && (((addr + size) - 1) <= (Xcp_SegmentInfo.pageInfoPtr[segmentNum].ramEnd)))
                #endif
                {
                    result = TRUE;
                    break;
                }
            }
            #endif
            break;
        }
        default:
            break;
    }
    return result;
}
#endif

/*=======[E N D   O F   F I L E]==============================================*/

